package com.xiongjie.SingleLimit.algorithm;

import com.google.common.util.concurrent.RateLimiter;

import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

/**
 * 使用guava的默认限流器==令牌桶限流器【封装了桶，定时添加令牌这些操作，用户只需要在请求到来时调用获取令牌方法即可，根据返回值操作】
 * <p>
 * 实现是通过预支后面的令牌来进行的，前面的坑，后面的来填
 * <p>
 * 使用RateLimiter，这里主要考虑的是速度，不是令牌桶的上限
 * <p>
 * RateLimiter.create(10)==创建令牌桶限流器
 * RateLimiter.create(10,1,TimeUnit.SECONDS)==创建漏桶限流器
 */
public class RateLimiterWithGuava {

    //RateLimiter定时完成添加令牌的效果,guava的后台实现是数字的加减乘除法
    private RateLimiter rateLimiter = RateLimiter.create(10);     //每秒执行10次的速度，令牌桶上限就为10,不用手动设置令牌桶大小

    public boolean visit() {
        //指定时间范围内获取1个令牌
        boolean success = rateLimiter.tryAcquire(1, TimeUnit.SECONDS);
        if (success) {
            System.out.println("请求成功");
            return true;
        } else {
            System.out.println("大流量来袭，请求超时");
            return false;
        }
    }

    public static void main(String[] args) {

        final RateLimiterWithGuava tokenBuck = new RateLimiterWithGuava();

        //模拟发送30个请求
        IntStream.range(0, 30).forEach(i -> {
            new Thread(tokenBuck::visit).start();
        });
    }

}
